//小偷又发现了一个新的可行窃的地区。这个地区只有一个入口，我们称之为
// root 。
//
// 除了
// root 之外，每栋房子有且只有一个“父“房子与之相连。一番侦察之后，聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的
//房子在同一天晚上被打劫 ，房屋将自动报警。
//
// 给定二叉树的 root 。返回 在不触动警报的情况下 ，小偷能够盗取的最高金额 。
//
//
//
// 示例 1:
//
//
//
//
//输入: root = [3,2,3,null,3,null,1]
//输出: 7
//解释:小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7
//
// 示例 2:
//
//
//
//
//输入: root = [3,4,5,1,3,null,1]
//输出: 9
//解释:小偷一晚能够盗取的最高金额 4 + 5 = 9
//
//
//
//
// 提示：
//
//
//
//
//
// 树的节点数在 [1, 10⁴] 范围内
// 0 <= Node.val <= 10⁴
//
//
// Related Topics 树 深度优先搜索 动态规划 二叉树 👍 1679 👎 0


//leetcode submit region begin(Prohibit modification and deletion)
/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     val: number
 *     left: TreeNode | null
 *     right: TreeNode | null
 *     constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.left = (left===undefined ? null : left)
 *         this.right = (right===undefined ? null : right)
 *     }
 * }
 */

function rob(root: TreeNode | null): number {
    /*?
    ?   1.确定递归函数的参数和返回值
            ? 要求一个节点 偷与不偷的两个状态所得到的金钱，那么返回值就是一个长度为2的数组。
            ? 所以dp数组（dp table）以及下标的含义：下标为0记录不偷该节点所得到的的最大金钱，下标为1记录偷该节点所得到的的最大金钱。
    ?   2.确定终止条件
            ? 在遍历的过程中，如果遇到空节点的话，很明显，无论偷还是不偷都是0，所以就返回。这也相当于dp数组的初始化
    ?   3.确定遍历顺序
            ? 首先明确的是使用后序遍历。 因为要通过递归函数的返回值来做下一步计算。
            ? 通过递归左节点，得到左节点偷与不偷的金钱。
            ? 通过递归右节点，得到右节点偷与不偷的金钱。
    ?   4.确定单层递归的逻辑
            ? 如果是偷当前节点，那么左右孩子就不能偷，val1 = cur->val + left[0] + right[0]; （如果对下标含义不理解就再回顾一下dp数组的含义）
            ? 如果不偷当前节点，那么左右孩子就可以偷，至于到底偷不偷一定是选一个最大的，所以：val2 = max(left[0], left[1]) + max(right[0], right[1]);
            ? 最后当前节点的状态就是{val2, val1}; 即：{不偷当前节点得到的最大金钱，偷当前节点得到的最大金钱}
        5.
    ? */

//? 返回数组中最大的值
    return Math.max(...robNode(root));
};
//? 下标为0记录不偷该节点所得到的的最大金钱，下标为1记录偷该节点所得到的的最大金钱
type MaxValueArr = [number, number];
function robNode(node) :MaxValueArr {
    if (node === null) return [0, 0];
    //? 后序遍历
    const leftArr: MaxValueArr = robNode(node.left);
    const rightArr: MaxValueArr = robNode(node.right);
    //? 不偷当前节点 那么可以偷左右节点(偷不偷害的看钱多不多咯)
    const val1 = Math.max(leftArr[0],leftArr[1]) + Math.max(rightArr[0],rightArr[1])
    //? 偷当前节点 那么左右节点都不能偷
    const val2 = leftArr[0] + rightArr[0] + node.val
    //? 看偷哪个的钱多
    return [val1,val2]
}
//leetcode submit region end(Prohibit modification and deletion)
